package com.api.user.service.impl;

import com.api.core.config.AuthUser;
import com.api.user.dao.TeamMapper;
import com.api.user.dao.TeamUserMapper;
import com.api.user.model.Game;
import com.api.user.model.Team;
import com.api.user.model.TeamUser;
import com.api.user.service.GameService;
import com.api.user.service.TeamService;
import com.api.core.service.AbstractService;
import com.api.user.vo.GameVo;
import com.api.user.vo.TeamTournamentVo;
import com.api.user.vo.TeamVo;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.collect.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

import com.api.common.JSONUtils;
import com.api.core.response.Result;
import com.api.core.response.ResultGenerator;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.util.CollectionUtils;

/**
 * Created by wanghuiwen on 2021/03/26.
 */
@Service
@Transactional
public class TeamServiceImpl extends AbstractService<Team> implements TeamService {
    @Resource
    private TeamMapper teamMapper;

    @Resource
    private TeamUserMapper teamUserMapper;
    @Resource
    private GameService gameService;

    @Override
    public Result list(Map<String, Object> params, String order, Integer page, Integer size){
//        Map<String, Object> params = JSONUtils.json2map(search);
        Map<String, Object> orderParams = JSONUtils.json2map(order);
        for (String key : orderParams.keySet()) {
                if (orderParams.get(key) != null && orderParams.get(key).equals("ascending")) orderParams.put(key, "asc");
                if (orderParams.get(key) != null && orderParams.get(key).equals("descending")) orderParams.put(key, "desc");
            }
        PageHelper.startPage(page, size);
        orderParams.put("create_time","desc");
        List<Map<String, Object>> res = teamMapper.list(params, orderParams);
        for (Map<String, Object> map: res
             ) {
            Map<String,Object> find = new HashMap<>();
            Long teamId =(Long) map.get("teamId");
            find.put("teamId",teamId);
            find.put("agree",2);
            List<Map<String, Object>> res1 = teamUserMapper.list(find, new HashMap<String, Object>());
            map.put("member",res1.size());
        }
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>(res);
        return ResultGenerator.genSuccessResult(pageInfo);
    }

    @Override
    public Result achievement(Long teamId) {
        Map<String, Object> map = teamMapper.achievement(teamId);
        Map<String,Object> find = new HashMap<>();
        find.put("teamId",teamId);
//        find.put("type","apply");
        find.put("agree",2);
        //参赛数量
        Integer countTournamentO =  teamMapper.countTournament(teamId,"officially");
        Integer countTournamentP =  teamMapper.countTournament(teamId,"privately");
        Integer countF =  teamMapper.countRank(teamId,1);
        Integer countS =  teamMapper.countRank(teamId,2);
        Integer countT =  teamMapper.countRank(teamId,3);

        List<Map<String, Object>> res1 = teamUserMapper.list(find, new HashMap<String, Object>());
        map.put("member",res1);
        map.put("champion",countF);
        map.put("runnerUp",countS);
        map.put("thirdPlace",countT);
        map.put("officially",countTournamentO);
        map.put("privately",countTournamentP);
        return ResultGenerator.genSuccessResult(map);
    }


    @Override
    public Result add(Team team) {
        Team identicalName = teamMapper.selectByName(team.getTeamName(),team.getGameId());
        if(team.getTeamId()!=null){
            Team old = findById(team.getTeamId());
            if(identicalName != null && !identicalName.getTeamId().equals(old.getTeamId())){
                return ResultGenerator.genFailResult(400,team.getTeamName() + "have same team");
            }

            if(!old.getAnnouncement().equals(team.getAnnouncement())){
                team.setAnnouncementTime(new Date().getTime());
            }else {
                team.setUpdateTime(new Date().getTime());
            }
            this.update(team);
        }else{
            if(identicalName!=null){
                return ResultGenerator.genFailResult(400,team.getTeamName() + "have same team");
            }

            team.setUpdateTime(new Date().getTime());
            team.setCreateTime(new Date().getTime());
            this.save(team);
            TeamUser teamUser = new TeamUser();
            teamUser.setTeamId(team.getTeamId());
            teamUser.setUserId(team.getLeaderId());
            teamUser.setCreateTime(new Date().getTime());
            teamUser.setJoinedTime(new Date().getTime());
            teamUser.setAgree(2);
            teamUser.setType("invite");
            teamUserMapper.insert(teamUser);
        }
        return ResultGenerator.genSuccessResult(team.getTeamId());
    }

    @Override
    public Result tournaments(Map<String, Object> params, Integer page, Integer size) {
//        PageHelper.startPage(page, size);
        List<TeamTournamentVo> res = teamMapper.tournaments(params);
//        PageInfo<ResultMap<String, Object>> pageInfo = new PageInfo<>(res);
        return ResultGenerator.genSuccessResult(res);
    }

    @Override
    public Result userList(Map<String, Object> params, AuthUser authUser) {
        params.put("userId",authUser.getId());
        List<TeamVo> res = teamUserMapper.userList(params);
        return ResultGenerator.genSuccessResult(res);
    }

    @Override
    public Map<Long, TeamVo> getIdVoMap(List<Long> teamIds) {
        if (CollectionUtils.isEmpty(teamIds)) {
            return Collections.emptyMap();
        }
        String teamIdStr = Joiner.on(",").join(teamIds);
        List<Team> teams = teamMapper.selectByIds(teamIdStr);
        ImmutableSet<Long> gameIds = FluentIterable.from(teams)
                .transform(new Function<Team, Long>() {
                    @Override
                    public Long apply(Team input) {
                        return input.getGameId();
                    }
                }).toSet();
        final Map<Long, GameVo> gameIdMap = gameService.getIdVoMap(gameIds);
        ImmutableList<TeamVo> teamVos = FluentIterable.from(teams)
                .transform(new Function<Team, TeamVo>() {
                    @Override
                    public TeamVo apply(Team input) {
                        TeamVo teamVo = new TeamVo();
                        teamVo.setTeamId(input.getTeamId());
                        teamVo.setTeamName(input.getTeamName());
                        teamVo.setTeamLogo(input.getTeamLogo());
                        teamVo.setGameName(Optional.fromNullable(gameIdMap.get(input.getGameId())).transform(new Function<GameVo, String>() {
                            @Override
                            public String apply(GameVo input) {
                                return input.getName();
                            }
                        }).orNull());
                        teamVo.setTeamSlogan(input.getTeamSlogan());
                        return teamVo;
                    }
                }).toList();
        return Maps.uniqueIndex(teamVos, new Function<TeamVo, Long>() {
            @Override
            public Long apply(TeamVo input) {
                return input.getTeamId();
            }
        });
    }

    @Override
    public Map<Long, List<Integer>> batchCountRank(List<Long> teamIds) {
        List<Map<String, Object>> mapList = teamMapper.batchCountRank(teamIds);
        Map<Long, List<Integer>> result = Maps.newHashMapWithExpectedSize(mapList.size());
        for (Map<String, Object> map : mapList) {
            List<Integer> counts = new ArrayList<>(3);
            counts.add(((Number) map.get("champions")).intValue());
            counts.add(((Number) map.get("runnerUps")).intValue());
            counts.add(((Number) map.get("thirdPlaces")).intValue());
            result.put(((Number) map.get("teamId")).longValue(), counts);
        }
        for (Long teamId : teamIds) {
            if (result.get(teamId) == null) {
                result.put(teamId, Lists.newArrayList(0, 0, 0));
            }
        }
        return result;
    }

    @Override
    public Result transfer(Long toUser, Long teamId, Long id) {
        Team team  =  findById(teamId);
        if(!team.getLeaderId().equals(id)){
            return ResultGenerator.genFailResult(400,"Only team leader can handover leadership to member.");
        }
        TeamUser user = teamUserMapper.getByTeamIdAndUserId(teamId,toUser);
        if(user==null){
            return ResultGenerator.genFailResult(400,"Can only handover leadership to team member.");
        }
        team.setLeaderId(toUser);
        update(team);

        return ResultGenerator.genSuccessResult();
    }

    @Override
    public Result moveto(Long teamId, Long userId, Long toTeamId) {
        Team team = findById(teamId);

        TeamUser teamUser = teamUserMapper.getByTeamIdAndUserId(teamId,userId);

        /**
         * 从原来的队伍删除
         */
        teamUserMapper.deleteNew(teamUser);

        TeamUser newUser = teamUserMapper.getByTeamIdAndUserId(toTeamId,userId);
        if(newUser!=null){
            newUser.setAgree(2);
            teamUserMapper.updateNew(newUser);
        }else {
            newUser = new TeamUser();
            newUser.setTeamId(toTeamId);
            newUser.setUserId(userId);
            newUser.setCreateTime(new Date().getTime());
            newUser.setJoinedTime(new Date().getTime());
            newUser.setAgree(2);
            newUser.setType("transfer");
            teamUserMapper.insert(newUser);
        }

        return ResultGenerator.genSuccessResult();
    }
}
